package com.example.check_in.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.example.check_in.feign.PaymentFeignClient;
import com.example.check_in.feign.RoomFeignClient;
import com.example.check_in.mapper.CheckInGuestMapper;
import com.example.check_in.mapper.CheckInMapper;
import com.example.check_in.mapper.DepositMapper;
import com.example.check_in.mapper.ScheduleMapper;
import com.example.check_in.service.ScheduleService;
import com.example.check_in.util.IdWorker;
import com.example.core.exception.HotelException;
import com.example.model.check_in.CheckIn;
import com.example.model.check_in.Deposit;
import com.example.model.check_in.OrderDo;
import com.example.model.check_in.ScheduleCheckIn;
import com.example.model.payment.Payment;
import com.example.model.payment.PaymentResultVo;
import com.example.model.room.Room;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Formatter;
import java.util.List;

import static com.example.model.constants.CodeConstants.RESERVE_ERROR;
import static com.example.model.constants.ServiceConstants.DEPOSIT_DISCOUNT;

@Service
public class ScheduleServiceImpl implements ScheduleService {

    private ScheduleCheckIn scheduleCheckIn;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private ScheduleMapper scheduleMapper;

    @Autowired
    private DepositMapper depositMapper;

    @Autowired
    private CheckInMapper checkInMapper;

    @Autowired
    private CheckInGuestMapper checkInGuestMapper;

    @Autowired
    private RoomFeignClient roomFeignClient;

    @Autowired
    private PaymentFeignClient paymentFeignClient;

    @Override
    public ScheduleCheckIn startSchedule() {
        scheduleCheckIn = new ScheduleCheckIn(idWorker.getId("schedule"));
        return scheduleCheckIn;
    }

    @Override
    public CheckIn enterInfo(OrderDo order) {
        CheckIn checkIn = new CheckIn(idWorker.getId("order"));
        List<CheckIn> checkInList = checkInMapper.listByDate(order.getCheckInDate());
        if (checkInList.size() >= 3){
            throw new HotelException(RESERVE_ERROR, "当天预定已达上限");
        }
        Room room = BeanUtil.toBean(roomFeignClient.get(order.getRoomNo()).getData(), Room.class);
        order.getCheckInGuests().forEach(checkInGuest -> {
            checkInGuest.setCheckInId(checkIn.getId());
        });
        checkIn.setGuests(order.getCheckInGuests());
        checkIn.setRoom(room);
        checkIn.setStatus(1);
        checkIn.setScheduleFlag(1);
        checkIn.setAmount(room.getRoomType().getPriceRule().getPrice()
                .multiply(BigDecimal.valueOf(order.getCheckInDay())));
        LocalDateTime checkInDate = LocalDate.parse(order.getCheckInDate()).atTime(12, 0, 0, 0);
    //            LocalDateTime checkInTime = LocalDateTime.now().withHour(12).withMinute(0).withSecond(0).withNano(0);
        checkIn.setCheckInDate(checkInDate);
        checkIn.setCheckOutDate(checkInDate.plusDays(order.getCheckInDay()));

        scheduleCheckIn.setId(checkIn.getId());
        scheduleCheckIn.setCheckIn(checkIn);
        scheduleCheckIn.setIsFinish(0);

        return checkIn;
    }

    @Override
    @Transactional
    public ScheduleCheckIn confirmInfo() {
        Deposit deposit = new Deposit(idWorker.getId("deposit"));
        deposit.setDepositAmount(scheduleCheckIn.getCheckIn().getAmount().multiply(DEPOSIT_DISCOUNT));
        deposit.setIsRefund(0);
        scheduleCheckIn.setDeposit(deposit);
        insert(scheduleCheckIn);
        checkInMapper.enterInfo(scheduleCheckIn.getCheckIn());
        checkInGuestMapper.insertBatch(scheduleCheckIn.getCheckIn().getGuests());
        depositMapper.insert(deposit);
        return scheduleCheckIn;
    }

    @Override
    @Transactional
    public PaymentResultVo makeDepositPayment(String paymentType, BigDecimal pay) {
        Deposit deposit = scheduleCheckIn.getDeposit();
        Payment payment = new Payment();
        payment.setPaymentId(idWorker.getId("payment"));
        payment.setPaymentType(paymentType);
        PaymentResultVo paymentResultVo = BeanUtil.toBean(
                paymentFeignClient.makePayment(payment, deposit.getDepositAmount(), pay).getData(), PaymentResultVo.class);
        deposit.setPaymentId(paymentResultVo.getPaymentId());
        deposit.setPayment(payment);
        depositMapper.update(deposit);
        scheduleMapper.update(scheduleCheckIn);
        return paymentResultVo;
    }

    @Override
    public int insert(ScheduleCheckIn scheduleCheckIn) {
        return scheduleMapper.insert(scheduleCheckIn);
    }

    @Override
    public ScheduleCheckIn get(Long checkInId) {
        return scheduleMapper.get(checkInId);
    }

    @Override
    public List<ScheduleCheckIn> list(ScheduleCheckIn scheduleCheckIn) {
        return scheduleMapper.list(scheduleCheckIn);
    }

    @Override
    public int update(ScheduleCheckIn scheduleCheckIn) {
        return scheduleMapper.update(scheduleCheckIn);
    }

}
